package com.hadron.file 
{
	import temple.data.encoding.image.JPGEncoder;

	import com.hadron.file.events.FileUtilEvent;
	import com.hadron.file.events.FileUtilProgressEvent;

	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.net.*;
	import flash.utils.ByteArray;
	//import com.adobe.images.BMPEncoder;	
	
	/**
	 * ...
	 * @author Hadron
	 */
	public class FileUtil extends Sprite implements IFileUtil
	{
		protected var _uploadScriptURL:String = 'file_upload.php';
		protected var _uploadDir:String = 'upload';
		protected var _uploadURL:URLRequest;
		protected var _file:FileReference;
		protected var _filePath:String;
		protected var _saveURL:String = "file_save.php";
		protected var _imageID:String = '';
		
		public function FileUtil() 
		{
			super();
			init();
		}
		
		private function init():void
		{
			trace('adding listeners');
			_file = new FileReference();
			_uploadURL = new URLRequest(_uploadScriptURL + '?uploadDir=' + _uploadDir);
			_file.addEventListener(Event.SELECT, handleSelectFile, false, 0, true);
			_file.addEventListener(Event.OPEN, handleOpenFile, false, 0, true);
			_file.addEventListener(HTTPStatusEvent.HTTP_STATUS, handleHttpStatus, false, 0, true);
			_file.addEventListener(Event.COMPLETE, handleCompleteUpload, false, 0, true);
			_file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, handleSecurityError, false, 0, true);
			_file.addEventListener(IOErrorEvent.IO_ERROR, handleIoError, false, 0, true);
			_file.addEventListener(ProgressEvent.PROGRESS, handleUploadProgress, false, 0, true);
			_file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, handleUploadComplete, false, 0, true);
		}
		
		private function handleSelectFile(e:Event):void 
		{
			trace("[FileUtil] File Selected");
			dispatchEvent(new FileUtilEvent(FileUtilEvent.FILE_SELECT));
		}
		
		public function upload():void
		{
			//upload the file
			_file.upload(_uploadURL);
		}
		
		private function handleOpenFile(e:Event):void 
		{
			trace("[FileUtil] File Upload Started");
		}
		
		private function handleCompleteUpload(e:Event):void 
		{
			trace("[FileUtil] File Upload Complete");
			dispatchEvent(new FileUtilEvent(FileUtilEvent.UPLOAD_COMPLETE));
		}
		
		private function handleHttpStatus(e:HTTPStatusEvent):void 
		{
			trace("[FileUtil] HTTP Status: " + e.status);
			//dispatchEvent(new FileUtilEvent(FileUtilEvent.UPLOAD_FAIL));
		}
		
		private function handleSecurityError(e:SecurityErrorEvent):void 
		{
			trace("[FileUtil] Security Error: " + e.text);
			dispatchEvent(new FileUtilEvent(FileUtilEvent.UPLOAD_FAIL));
		}
		
		private function handleIoError(e:IOErrorEvent):void
		{
			trace("[FileUtil] IOError: " + e.text);
			dispatchEvent(new FileUtilEvent(FileUtilEvent.UPLOAD_FAIL));
		}
		
		private function handleUploadProgress(e:ProgressEvent):void 
		{
			//trace("[FileUtil] progress: " + e.bytesLoaded + " / " + e.bytesTotal);
			//this.progress_bar.setProgress(e.bytesLoaded, e.bytesTotal);
			//this.progress_txt.text = Math.round((e.bytesLoaded / e.bytesTotal) * 100) + "%";
			dispatchEvent(new FileUtilProgressEvent(FileUtilProgressEvent.PROGRESS, false, false, e.bytesLoaded, e.bytesTotal));
		}
		
		private function handleUploadComplete(e:DataEvent):void 
		{
			trace("[FileUtil] File Upload DATA Complete");
			_filePath = _uploadDir + '/' + _file.name;
			dispatchEvent(new FileUtilEvent(FileUtilEvent.UPLOAD_COMPLETE));
		}
		
		/* INTERFACE */
		public function set uploadScriptURL(value:String):void
		{
			if (value != null)
			{
				_uploadScriptURL = value;
				_uploadURL.url = _uploadScriptURL + '?uploadDir=' + _uploadDir;
			}	
		}
		
		public function get uploadScriptURL():String
		{
			return _uploadScriptURL;
		}
		
		public function browse():void 
		{
			_file.browse([new FileFilter("All Formats (*.jpg,*.gif,*.png,)", "*.jpg;*.gif;*.png;", "JPEG;jp2_;GIFF;")]);
		}
		
		public function download():void
		{
			trace('FileName: ' + _file.name);
			_filePath = _uploadDir + '/' + _file.name;
			var fileURL:URLRequest = new URLRequest(_filePath);
			_file.download(fileURL);
		}
		
		public function deleteFileFromServer():void
		{
			var request:URLRequest = new URLRequest(_uploadScriptURL + '?delfile=' + filePath);
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, handleFileDelete, false, 0, true);
			loader.load(request);
		}
		
		private function handleFileDelete(e:Event):void 
		{
			trace("[FileUtil] File deleted from the server");
		}
		
		public function get filePath():String
		{
			return _filePath;
		}
		
		public function get fileName():String
		{
			return _file.name;
		}
		
		public function get fileSize():Number
		{
			return _file.size;
		}
		
		public function createJPG(m:MovieClip, q:Number, fileName:String='snapshot', maskerClip:MovieClip = null):void
		{
			//trace('maskerClip: ' + maskerClip);
			var ext:String = '.jpg';
			var jpgSource:BitmapData = (maskerClip == null) ? new BitmapData (m.width, m.height) : new BitmapData(maskerClip.width, maskerClip.height);
			 
			if (maskerClip == null)
			{
				jpgSource.draw(m);
			} else {
				
				//trace('drawing image with mask');
				m.mask = null;
				var matrix:Matrix = new Matrix();
				matrix.scale(m.scaleX, m.scaleY);
				var radians:Number = (m.rotation / 180) * Math.PI;
				matrix.rotate(radians); 
			
				var valueX:Number = maskerClip.x - m.x;
				var valueY:Number = maskerClip.y - m.y;
				//trace('valueX: ' + valueX);
				//trace('valueY: ' + valueY);
				
				matrix.translate( -valueX, -valueY);
				//reattach mask
				jpgSource.draw(m, matrix);
				m.mask = maskerClip;
			}
			var jpgEncoder:JPGEncoder = new JPGEncoder(q);
			var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
			
			var header:URLRequestHeader = new URLRequestHeader ('Content-type', 'application/octet-stream');
			var jpgURLRequest:URLRequest = new URLRequest (_saveURL + '?name=' + getUniqueFileName(fileName) + ext);		
			
			jpgURLRequest.requestHeaders.push(header);				
			jpgURLRequest.method = URLRequestMethod.POST;				
			jpgURLRequest.data = jpgStream;
			
			var jpgURLLoader:URLLoader = new URLLoader();
			jpgURLLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
			jpgURLLoader.addEventListener(Event.COMPLETE, imageUrlLoaderComplete, false, 0, true);
			jpgURLLoader.addEventListener(IOErrorEvent.IO_ERROR, sendIOError, false, 0, true);
			jpgURLLoader.load(jpgURLRequest);
		}
		
		private function getUniqueFileName(fileName:String):String
		{
			var date:Date = new Date();
			return fileName + date.getTime();
		}
		
		private function sendIOError(e:IOErrorEvent):void 
		{
			trace('[FileUtil] Saving file error ocurred');
		}
		
		private function imageUrlLoaderComplete(e:Event):void 
		{
			trace('[FileUtil] Saving file completed');
			URLLoader(e.target).removeEventListener(Event.COMPLETE, imageUrlLoaderComplete);
			_imageID = URLLoader(e.target).data.id;
			dispatchEvent(new FileUtilEvent(FileUtilEvent.SAVE_COMPLETE));
		}
		
		public function get imageID():String
		{
			return _imageID;
		}
	}
}